home *** CD-ROM | disk | FTP | other *** search
/ Mac Format 1998 September / Macformat_MF67_1998-09.iso / Resources / System Add-ons / CDIconKiller 1.5 / sources / CDIconKiller.c < prev    next >
C/C++ Source or Header  |  1997-10-19  |  11KB  |  453 lines

  1. #ifndef __Assembler__
  2. #include    <Assembler.h>
  3. #endif
  4.  
  5. #include    "TrapAvailable.h"
  6. /*
  7. ; CDIconKiller © 1994-1997 Quinn & Peter N Lewis, Fabrizio Oddone
  8. ; Version 1.0 written in 4 hours from 02:00 to 05:30 18/June/94
  9.  
  10. bug fixes, CD driver string in resource (suggested by Quinn),
  11. asm tweaks, cdev trickery, etc.
  12. (version 1.1 thru 1.5) by Fabrizio Oddone
  13.  
  14. version 1.5 updated in 3 hours from 16:00 to 19:00 (CET) October 17, 1997
  15. dreaded "File Sharing startup crash" fixed from 10:00 to 11:00 October 18, 1997
  16. bottled wine (Barbera) in the afternoon -- BTW, check out the 1997 Italian wines: a most excellent crop this year
  17. LoadADrive compatibility reassessment & code tweaks from 15:00 to 17:00 October 19, 1997
  18.  
  19. ; Patches GetCatInfo, tests for Custom Icon attribute on
  20. ; CD-ROM files/folders, and clears it.
  21.  
  22. ; Detailed description:
  23.  
  24. ; now runs as a cdev so the patch affects only the Finder
  25. ; since there is no user interface, we can retain the old icon
  26.  
  27. ; macDev time:
  28. ;    check if we are running under System 7 or later
  29. ;        check if the patch is already installed
  30. ;        load the resource containing the driver strings
  31. ;        patch GetCatInfo
  32.  
  33. ; initDev time:
  34. ;    we are done, quit silently
  35.  
  36. ; GetCatInfo patch (simplified):
  37. ;    Test for GetCatInfo selector on _HFSDispatch, do nothing otherwise
  38. ;    Test for async call; if so, patch completion routine
  39. ;    Call thru
  40. ;    Return immediately on error (async calls are handled by the completion patch)
  41. ;    Return immediately unless Custom Icon bit set
  42. ;    Walk the volume queue looking for the vRefNum of the GetCatInfo
  43. ;    If we don't find it, we leave
  44. ;    If the command key is down, we leave
  45. ;    We determine whether the driver refnum has been seen already
  46. ;    If yes
  47. ;        determine if the custom icon bit must be cleared for this driver
  48. ;    If no
  49. ;        we scan the driver queue and update our lists
  50.  
  51. Very brief discussion about the async patch:
  52. We cannot simply tail patch the call (being async, it hasn't run yet);
  53. we can tail patch the completion routine, though.
  54. We don't handle the worst case scenario with many outstanding async calls, that is,
  55. many completion routine addresses to save. We only save ONE completion routine address.
  56. Basically our patch can be in two states: can/cannot handle an async call, i.e.
  57. can/cannot save the completion routine address.
  58. The state indicator is bit #0 in the completion routine address
  59. (routine addresses must be even, that's why this bit can be used).
  60. Moreover, we can use BCLR to atomically test and clear the bit,
  61. in order to eschew any foreseeable reentrancy problem.
  62.  
  63.     include    'sysequ.a'
  64.     include    'fsequ.a'
  65.     include    'traps.a'
  66.  
  67. ; procedure ShowIcon (id: integer; delta_x: integer);
  68.     import    ShowIcon
  69. main    proc    export
  70.  
  71. extern pascal void ShowIcon(short iconID, short pixels);
  72. */
  73. static void mypatch(void);
  74.  
  75. //#define patchSize    (EndHFSDispatch - OurHFSDispatch)
  76. #define    patchSize    (650)    // because of CodeWarrior asm limitations
  77. #define    HFSDispatchTrapNum    0x60
  78. #define    kNumKilledDrivers    15
  79. #define    kNumOtherDrivers    63
  80.  
  81. pascal long main(short message, short /*item*/, short /*numItems*/, short /*cPanelID*/, EventRecord */*theEvent*/, long cdevValue, DialogPtr /*cpDialog*/)
  82. {
  83. long    resp;
  84.  
  85. if (cdevValue) {
  86.     switch (message) {
  87.         case initDev:
  88.             return cdevGenErr;
  89.             break;
  90.         case macDev:
  91. // normally you shouldn't check against the System version but against individual features
  92. // but in this case we want to know whether custom icons are used by the Finder
  93.             if (TrapAvailable(_Gestalt)) {
  94.                 if (Gestalt(gestaltSystemVersion, &resp) == noErr)
  95.                     if (resp >= 0x700) {
  96.                         mypatch();
  97.                         return 1;
  98.                         }
  99.                 }
  100. // no _Gestalt => very old System (< 6.0.4)
  101.             return 0;    
  102.             break;
  103.         }
  104.     }
  105. return cdevValue;
  106. }
  107.  
  108. asm void mypatch(void)
  109. {
  110.     moveq    #HFSDispatchTrapNum,d0    // patch HFSDispatch
  111.     _GetOSTrapAddress
  112.     move.l    OurHFSDispatch,d0
  113.     cmp.l    (a0),d0
  114. // if the patch is already there do nothing
  115.     beq.s    bad
  116.     lea    oldHFSDispatch,a1
  117.     move.l    a0,(a1)
  118.  
  119.     subq.w    #4,sp
  120.     move.l    #'STR#',-(SP)
  121.     move.w    #128,-(sp)
  122.     _Get1Resource
  123.     move.l    (sp)+,d0
  124.     beq.s    bad
  125.     lea    stringH,a0
  126.     move.l    d0,(a0)    // remember string handle
  127.     move.l    d0,-(sp)
  128.     _DetachResource
  129.     
  130.     bsr    findDriverbyName
  131.  
  132.     move.l    #patchSize,d0
  133.     _NewPtr    //Sys
  134. // this block is installed in the System heap anyway, because
  135. // the Finder calls our cdev with the current zone set to the System zone
  136. // (at least under 7.5.5!)
  137. // in theory we should install everything in the Finder heap since it now
  138. // belongs there; but since the Finder malfunctions when its heap is low
  139. // (maybe the current zone is not set to the Finder zone for this reason)
  140. // we refrain from forcing the Finder zone with GetZone/SetZone
  141.     bne.s    baddisposepref
  142.  
  143.     movea.l    a0,a1
  144.     lea    OurHFSDispatch,a0
  145.     move.l    #patchSize,d0
  146.     _BlockMove
  147.  
  148.     moveq    #HFSDispatchTrapNum,d0
  149.     movea.l    a1,a0
  150.     _SetOSTrapAddress    
  151.  
  152. //    MOVE.L    #0xffff0080,-(SP)
  153. //    JSR    ShowIcon
  154. bad:
  155.     rts
  156.  
  157. baddisposepref:
  158.     movea.l    stringH,a0
  159.     _DisposHandle
  160.     rts
  161.  
  162. // BEGIN may run at interrupt time
  163. OurHFSDispatch:
  164.     cmp.w    #9,d0    // Test for GetCatInfo selector
  165.     bne.s    dontdoit
  166.  
  167. // the trap dispatcher always puts the trapword in register D1
  168.     btst    #10,d1    // sync?
  169.     beq.s    tailpatch    // tail patch only sync calls
  170.  
  171. // for async calls, we intercept the completion routine
  172.     move.l    a1,-(sp)
  173.     lea        savedCompletion+3,a1
  174.     bclr    #0,(a1)    // test and clear -- be reentrant!
  175.     beq.s    restoreA1fin    // cannot save over existing completion
  176.  
  177.     subq.w    #3,a1    // point to savedCompletion
  178.     move.l    struct (DirInfo.ioCompletion)(a0),(a1)    // save
  179.     lea        myCompletion,a1
  180.     move.l    a1, struct (DirInfo.ioCompletion)(a0)    // put our own
  181. restoreA1fin:
  182.     movea.l    (sp)+,a1
  183.     bra.s        dontdoit
  184.  
  185. tailpatch:
  186.     pea    continued
  187. dontdoit:
  188.     move.l    oldHFSDispatch,-(sp)    // Call thru
  189.     rts
  190. // END may run at interrupt time
  191.  
  192. continued:
  193.     tst.w    struct (DirInfo.ioResult)(a0)
  194.     bne.s    fin    // give up on error
  195.  
  196.     btst    #2,struct (DirInfo.ioDrUsrWds.frFlags)(a0)
  197.     beq.s    fin    // give up unless custom icon
  198.     
  199.     movem.l    a1/d1,-(sp)
  200.     
  201.     bsr        cmdkeyisdown
  202.     bne.s    leave
  203.  
  204.     movea.l    0x358,a1    // first volume control block LMGetVCBQHdr()+2
  205.     move.w    struct (DirInfo.ioVRefNum)(a0),d1
  206. lop:
  207.     cmp.w    struct (VCB.vcbVRefNum)(a1),d1
  208.     bne.s    cont
  209.  
  210.     move.w    struct (VCB.vcbDRefNum)(a1),d1
  211.     bsr    finddriverdontwantcustomicons
  212.     bne.s    clearcustombit
  213.     bsr    finddriverwantcustomicons
  214.     bne.s    leave
  215.     bsr    findDriverbyName
  216.     bra.s    leave
  217. clearcustombit:
  218.     bclr    #2,struct (DirInfo.ioDrUsrWds.frFlags)(a0)    // clear custom icon
  219.     bra.s    leave
  220.  
  221. cont:
  222.     movea.l    (a1),a1    // next volume control block
  223.     move.l    a1,d0
  224.     bne.s    lop
  225.  
  226. leave:
  227.     movem.l    (sp)+,a1/d1
  228.     moveq    #0,d0
  229.     
  230. fin:
  231.     tst.w    d0
  232. notstfin:
  233.     rts
  234.  
  235. // BEGIN may run at interrupt time
  236. cmdkeyisdown:
  237.     MOVE.L    A0,-(SP)
  238.     LEA    -sizeof(EventRecord)(SP),SP
  239.     MOVEA.L    SP,A0
  240.     MOVEQ    #0,D0
  241.     _OSEventAvail    // can be called at interrupt time; cool isn't it?
  242.     BTST    #0,struct (EventRecord.modifiers)(A0)    //cmdKey
  243.     LEA    sizeof(EventRecord)(SP),SP
  244.     MOVEA.L    (SP)+,A0
  245.     RTS
  246.  
  247. myCompletion:
  248.     tst.w    struct (DirInfo.ioResult)(a0)
  249.     bne.s    endcompletion    // give up on error
  250.  
  251.     btst    #2,struct (DirInfo.ioDrUsrWds.frFlags)(a0)
  252.     beq.s    endcompletion    // give up unless custom icon
  253.     
  254.     bsr        cmdkeyisdown
  255.     bne.s    endcompletion
  256.  
  257.     movea.l    0x358,a1    // first volume control block LMGetVCBQHdr()+2
  258.     move.w    struct (DirInfo.ioVRefNum)(a0),d1
  259. comploop:
  260.     cmp.w    struct (VCB.vcbVRefNum)(a1),d1
  261.     bne.s    compcont
  262.  
  263.     move.w    struct (VCB.vcbDRefNum)(a1),d1
  264.     bsr.s    finddriverdontwantcustomicons
  265.     beq.s    endcompletion
  266.     bclr    #2,struct (DirInfo.ioDrUsrWds.frFlags)(a0)    // clear custom icon
  267.     bra.s    endcompletion
  268. compcont:
  269.     movea.l    (a1),a1    // next volume control block
  270.     move.l    a1,d0
  271.     bne.s    comploop
  272.  
  273. endcompletion:
  274.     movea.l    savedCompletion,a1
  275.     move.l    a1,struct (DirInfo.ioCompletion)(a0)    // without this line, File Sharing will crash when starting up!
  276.     beq.s    nilcompletion
  277.     jsr    (a1)
  278. nilcompletion:
  279.     lea    savedCompletion+3,a1
  280.     bset    #0,(a1)    // can reuse for next async call
  281.     
  282.     rts
  283.  
  284. finddriverdontwantcustomicons:
  285.     move.l    a0,-(sp)
  286.     lea    lastskipthesedrivers,a0
  287.     bset    #7,(a0)    // eschew reentrancy problems; all drivers should have negative refnum
  288.     bne.s    alreadyinitiated
  289.     move.w    d1,(a0)
  290.     lea    skipthesedrivers,a0
  291. loopfinddontwant:
  292.     cmp.w    (A0)+,D1
  293.     bne.s    loopfinddontwant
  294.  
  295.     move.l    a0,-(SP)
  296.     lea    lastskipthesedrivers,a0
  297.     bclr    #7,(a0)    // clear
  298.     movea.l    (sp)+,a0
  299.  
  300. alreadyinitiated:
  301.     pea    lastskipthesedrivers+2
  302.     cmpa.l    (SP)+,A0
  303.     movea.l    (sp)+,a0
  304.     rts
  305. // END may run at interrupt time
  306.  
  307. finddriverwantcustomicons:
  308.     move.l    a0,-(sp)
  309.     lea    lastotherdrivers,a0
  310.     move.w    D1,(a0)
  311.     lea    otherdrivers,a0
  312. loopfindwant:
  313.     cmp.w    (A0)+,D1
  314.     bne.s    loopfindwant
  315.     pea    lastotherdrivers+2
  316.     cmpa.l    (sp)+,A0
  317.     movea.l    (sp)+,a0
  318.     rts
  319.  
  320. findDriverbyName:
  321.     movem.l    a0-a4/a6/d1/d3-d5,-(sp)
  322.     moveq    #0,d5
  323.     lea    nextfreedontwant,a3
  324.     tst.w    (a3)
  325.     bge.s    alreadyinitednfdw
  326.     st    d5
  327.     clr.w    (a3)
  328. alreadyinitednfdw:
  329.     moveq    #(kNumKilledDrivers*2),d0
  330.     cmp.w    (a3),d0
  331.     beq.s    plainexit
  332.  
  333.     lea    nextfreewant,a4
  334.     moveq    #(kNumOtherDrivers*2),d0
  335.     cmp.w    (a4),d0
  336.     beq.s    plainexit
  337.  
  338.     movea.l    0x11C,a2    // LMGetUTableBase()
  339.     move.w    0x1d2,d3    // LMGetUnitTableEntryCount()
  340. loop:
  341.     move.l    (a2)+,d0
  342.     beq.s    endloop
  343.     movea.l    d0,a1
  344.  
  345. // a1 = curDCtlHndl
  346.  
  347.     movea.l    (a1),a1
  348.     move.l    /*struct (DCtlEntry.dCtlDriver)*/(a1),d0
  349.     beq.s    endloop
  350.     movea.l    d0,a0
  351.     btst    #6,(struct (DCtlEntry.dCtlFlags)+1)(a1)    // test for RAMDriver
  352.     beq.s    notram
  353.     move.l    (a0),d0
  354.     beq.s    endloop
  355.     movea.l    d0,a0
  356. notram:
  357.     move.w    d3,d4
  358.     sub.w    0x1d2,d4    // calc driver refnum -(unit num+1) LMGetUnitTableEntryCount()
  359.     subq.w    #1,d4
  360.     tst.b    d5
  361.     bne.s    firsttime
  362.     move.w    d4,d1
  363.     bsr    finddriverdontwantcustomicons
  364.     bne.s    endloop
  365.     bsr    finddriverwantcustomicons
  366.     bne.s    endloop
  367. firsttime:
  368.     lea    struct (DRVRHeader.drvrName)(a0),a0
  369.     moveq    #0,d2
  370.     move.b    (a0)+,d2
  371.     swap    d2
  372.     bsr    cmpallstrings
  373.     bne.s    endloopsavedriver
  374.  
  375.     lea    skipthesedrivers,a0
  376.     movea.l    a3,a1
  377.     bra.s    commonpart
  378. endloopsavedriver:
  379.     lea    otherdrivers,a0
  380.     movea.l    a4,a1
  381. commonpart:
  382.     adda.w    (a1),a0
  383.     move.w    d4,(a0)    // remember driver refnum
  384.     addq.w    #2,(a1)
  385. endloop:
  386.     subq.w    #1,d3
  387.     bne    loop
  388. plainexit:
  389.     movem.l    (sp)+,a0-a4/a6/d1/d3-d5
  390.     rts
  391.  
  392. // input: a0 string, d2 (already in hi word) length
  393. // output: sets the flags
  394. // registers are saved&restored by the caller
  395. cmpallstrings:
  396.     movea.l    stringH,a6
  397.     movea.l    (a6),a6
  398.     move.w    (a6)+,d1
  399.     andi    #0xB,CCR
  400.     bra.s    thedbcc
  401. cmploop:
  402.     move.l    d2,d0
  403.     move.b    (a6)+,d0
  404.     movea.l    a6,a1
  405.     adda.w    d0,a6
  406.     _CmpString
  407. thedbcc:
  408.     dbeq    d1,cmploop
  409. cmpexit:
  410.     rts
  411.  
  412. // list of drivers whose disks won't display custom icons
  413. skipthesedrivers:
  414.     ds.w    kNumKilledDrivers
  415. lastskipthesedrivers:
  416.     dc.w    1
  417. // list of the remaining drivers
  418. otherdrivers:
  419.     ds.w    kNumOtherDrivers
  420. lastotherdrivers:
  421.     dc.w    1
  422.  
  423. nextfreedontwant:
  424.     dc.w    -1
  425. nextfreewant:
  426.     dc.w    0
  427. stringH:
  428.     dc.l    0
  429. savedCompletion:
  430.     dc.l    1
  431. oldHFSDispatch:
  432.     dc.l    0xffffffff
  433. EndHFSDispatch:
  434.  
  435. //    string    pascal
  436.  
  437. }
  438. //    endp
  439.     
  440. //    end
  441.     
  442. /*
  443. asm -wb "{active}"
  444. (evaluate "{active}" =~ "/(?*:)®1(?*)/" )> dev:null
  445. (evaluate "{active}" =~ "/(?*)®2.a/" )> dev:null
  446. link -rt INIT=128 -ra =ressysheap,reslocked -t INIT -c CDik -o "{®2}" "{active}.o" "{®1}ShowIcon.o"
  447. setfile -a B "{®2}"
  448.  
  449.  
  450.  
  451. dumpobj "{®1}SHOWICON.o"
  452. */
  453.